package container

type TypeId[K comparable] interface {
	GetTypeId() K
}

type TypeIdConstraint[K comparable] interface {
	TypeId[K]
	comparable
}

type TypeList[K comparable, T TypeIdConstraint[K]] struct {
	internal map[K]*Map[int64, T]
	all      []T
	cnt      int
}

func (l *TypeList[K, T]) Get(typeId K) []T {
	m, ok := l.internal[typeId]
	if !ok {
		return nil
	}
	return m.values
}

func (l *TypeList[K, T]) Add(key int64, data T) {
	typeId := data.GetTypeId()
	m, ok := l.internal[typeId]
	if !ok {
		m = NewMap[int64, T]()
		l.internal[typeId] = m
	}
	if m.Add(key, data) {
		l.all = append(l.all, data)
		l.cnt++
	}
}

func (l *TypeList[K, T]) Remove(key int64, data T) {
	typeId := data.GetTypeId()
	m, ok := l.internal[typeId]
	if ok {
		if m.Remove(key) {
			l.all = RemoveFromSlice(l.all, data)
			l.cnt--
		}
	}
}

func (l *TypeList[K, T]) RemoveAll(typeId K) []T {
	ret, ok := l.internal[typeId]
	l.internal[typeId] = NewMap[int64, T]()
	if !ok {
		return nil
	}
	for _, value := range ret.values {
		l.all = RemoveFromSlice(l.all, value)
	}
	return ret.values
}

func (l *TypeList[K, T]) Iterate(v ListVisitor[T]) {
	for index := range l.all {
		if !v(l.all[index]) {
			break
		}
	}
}

func (l *TypeList[K, T]) Count() int {
	return l.cnt
}

func NewTypeList[K comparable, V TypeIdConstraint[K]]() *TypeList[K, V] {
	return &TypeList[K, V]{internal: map[K]*Map[int64, V]{}}
}
